#include <fcntl.h>
#include <string.h>
#include <sys/epoll.h>

#include "../common/log.h"
#include "fd_event.h"

namespace rocket {

FdEvent::FdEvent() { memset(&m_listen_events, 0, sizeof(m_listen_events)); }

FdEvent::FdEvent(int fd) : m_fd(fd) {
    memset(&m_listen_events, 0, sizeof(m_listen_events));
}

FdEvent::~FdEvent() {}

std::function<void()> FdEvent::handler(TriggerEvent event) {
    if (event == TriggerEvent::IN_EVENT) {
        return m_read_callback;
    } else if (event == TriggerEvent::OUT_EVENT) {
        return m_write_callback;
    } else if (event == TriggerEvent::ERR_EVENT) {
        return m_error_callback;
    } else {
        return nullptr;
    }
}

void FdEvent::listen(TriggerEvent event_type, std::function<void()> callback, std::function<void()> error_callback /*= nullptr*/) {
    if (event_type == TriggerEvent::IN_EVENT) {
        m_listen_events.events |= EPOLLIN;
        m_read_callback = callback;
        m_listen_events.data.ptr = this;
    } else if (event_type == TriggerEvent::OUT_EVENT) {
        m_listen_events.events |= EPOLLOUT;
        m_write_callback = callback;
        m_listen_events.data.ptr = this;
    };
    m_error_callback = error_callback;
}

void FdEvent::setNonBlock() {
    int flag = fcntl(m_fd, F_GETFL, 0);
    if (flag & O_NONBLOCK) {
        return;
    }

    fcntl(m_fd, F_SETFL, flag | O_NONBLOCK);
    INFOLOG("hello");
}

void FdEvent::cancel(TriggerEvent event_type) {
    if (event_type == TriggerEvent::IN_EVENT) {
        m_listen_events.events &= (~EPOLLIN);
    } else {
        m_listen_events.events &= (~EPOLLOUT);
    }
}

} // namespace rocket
